package VideoProcessing;

import java.awt.image.WritableRaster;

import javax.media.format.VideoFormat;

public class BackgroundUpdater extends RgbVideoEffect {
	private BufferAccessor buffAcc;
	private long frameNumber = 0;
	private byte[] background = null; // until we know the frame dimensions
	private static final int BACKGROUND_GRAB_TIME = 1; // 30; // frames

	public BackgroundUpdater(BufferAccessor feedBufferAccessor) {
		buffAcc = feedBufferAccessor;
	}

	public byte[] getBackground() {
		return background;
	}

	public String getName() {
		return "Background Image Updater";
	}

	public void resetBackground() {
		frameNumber = BACKGROUND_GRAB_TIME - 1;
	}

	public boolean isCapturing() {
		return frameNumber <= BACKGROUND_GRAB_TIME;
	}

	/**
	 * Updates the background buffer. For now, we just copy the first frame
	 * verbatim (ASSUMES there are no moving objects in the first frame.
	 * 
	 * @param bin
	 *            MUST BE from the output of the BlobDetector or the
	 *            RgbThresholdEffect.
	 */
	@Override
	protected boolean processRGB(byte[] bin, byte[] bout, VideoFormat format) {
		if (background == null) {
			background = new byte[format.getSize().width
					* format.getSize().height*3];
		}
		if (frameNumber < BACKGROUND_GRAB_TIME) {
			System.out.print(frameNumber == 0 ? "Capturing background" : ".");

			if (buffAcc.getBuffer() != null) {
				System.out.println("Grabbing snapshot for background image");
				byte[] buffer = buffAcc.getBuffer();
				for (int i=0;i<buffer.length;i++) {
					background[i] = buffer[i];
				}
			} else {
				--frameNumber; // we didn't get that frame, so back up and don't
								// count it
			}
		} else {
			int p = 0; // background pixel pos
			int comp; // color component (rgb, 0-2)
			for (p = 0; p < background.length; p++) {
				if (bin[p] == 0) {
					if (((int) background[p] & 0xff) < ((int) (buffAcc
							.getBuffer()[p] & 0xff))) {
						++background[p];
					} else if (((int) background[p] & 0xff) > ((int) buffAcc
							.getBuffer()[p] & 0xff)) {
						--background[p];
					}

				}
			}
		}
		++frameNumber;
		return false;
	}

	@Override
	protected void updateImage(byte[] bout, VideoFormat vformat) {
		synchronized (displayImage) {
			System.arraycopy(background, 0, bout, 0, background.length);
			WritableRaster rast = displayImage.getRaster();
			int[] pixel = new int[] { 0, 0, 0, 255 };
			int p = 0;
			for (int y = vformat.getSize().height - 1; y >= 0; y--) {
				for (int x = 0; x < vformat.getSize().width; x++) {
					pixel[0] = pixel[1] = pixel[2] = bout[p++];
					rast.setPixel(x, y, pixel);
				}
			}
		}
	}

}
